Skip to content

Add python widget for Bloch Sphere - #3595

Open
Scott Carda (ScottCarda-MS) wants to merge 10 commits into
mainfrom
sccarda/PythonBloch
Open

Add python widget for Bloch Sphere#3595
Scott Carda (ScottCarda-MS) wants to merge 10 commits into
mainfrom
sccarda/PythonBloch

Conversation

@ScottCarda-MS

@ScottCarda-MS Scott Carda (ScottCarda-MS) commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Adds python support for the Bloch Sphere visualizer by making it a python widget, which is then added under the qsharp_widgets package, and additionally made available under the QDK python package.

Example python usage:

import qdk.widgets as w
bloch = w.BlochSphere('H T H') # string is initial gate sequence, can be empty
bloch

To minimize the impact of KaTeX on the Python package:

  • KaTeX CSS and fonts are isolated in a Bloch-specific stylesheet, so existing widgets continue loading the original lightweight stylesheet.
  • The production build retains only the four .woff2 font faces used by the Bloch sphere’s matrices and math expressions, reducing the Bloch stylesheet from approximately 383 KB to 109 KB raw (264 KB to 60 KB compressed).

@ScottCarda-MS
Scott Carda (ScottCarda-MS) marked this pull request as ready for review August 17, 2026 20:53

@billti Bill Ticehurst (billti) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To minimize the impact of KaTeX on the Python package:

KaTeX CSS and fonts are isolated in a Bloch-specific stylesheet, so existing widgets continue loading the original lightweight stylesheet.
The production build retains only the four .woff2 font faces used by the Bloch sphere’s matrices and math expressions, reducing the Bloch stylesheet from approximately 383 KB to 109 KB raw (264 KB to 60 KB compressed).

The index.js file for the widget however is 600kb larger after this PR (which is already too large as we still need to move the molecule visualizer out of it). This loads in every cell that just wants to show a histogram or a circuit or whatever.

As discussed, we should figure out how to make this a separate entry point so it only gets loaded when the user wants to see a Bloch sphere (which will prbably be pretty rarely). I can give you some guidance if needed.

Comment thread source/widgets/js/bloch.css
Comment thread source/widgets/js/index.tsx Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I built and tested the PR locally with the repository's Rust 1.95 toolchain. I left two inline comments:

  • The generated widget wheel embeds KaTeX assets but appears not to include KaTeX's MIT license notice.
  • Updating the synchronized initial_gates trait after display does not update the mounted Bloch Sphere; I included a minimal notebook reproducer and screenshot.

The widget otherwise built successfully and worked as expected in JupyterLab.

@ScottCarda-MS

Copy link
Copy Markdown
Contributor Author

The index.js file for the widget however is 600kb larger after this PR (which is already too large as we still need to move the molecule visualizer out of it). This loads in every cell that just wants to show a histogram or a circuit or whatever.

As discussed, we should figure out how to make this a separate entry point so it only gets loaded when the user wants to see a Bloch sphere (which will prbably be pretty rarely). I can give you some guidance if needed.

I've separated the bloch sphere into its own entry point with bloch.tsx, and removed it from index.tsx.

Comment thread source/widgets/js/bloch.tsx Outdated
@ScottCarda-MS
Scott Carda (ScottCarda-MS) marked this pull request as draft August 21, 2026 07:01
_initial_gates = traitlets.Unicode("").tag(sync=True)

@property
def initial_gates(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this property here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes the initial_gates read-only by letting me define a getter without a setter. This helps avoid the object having a state that can escape the GUI, reducing the complexity and avoiding situations where the GUI and the python object are out of sync.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants